Error: *** Deployment Failed ***
"Algorithm" hit a require or revert statement somewhere in its constructor. Try:
* Verifying that your constructor params satisfy all require conditions.
* Adding reason strings to your require statements.
1. やりたいこと
レポート情報を格納するためのデータ構造として、連想配列を使いたいと思っています。
実装が簡単そうな構造体配列をデータ構造とした場合は思ったようにコントラクトが書けたのですが、
それをベースに、連想配列にレポート情報を格納する実装を模索しています。
・構造体にレポート情報を格納する方針で実装した時コードと実行結果
( 実は、この時も一個問題があって、期待した値が返されていません。多分、原因は先日西野くんが質問したものと同じだと思います。あと、address型だと構造体配列に値を格納できなかったので、仕方なくstringで実装しています。)
code:Algorithm.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2; // 実験ライブラリらしい
contract Algorithm {
// Web3にレポートのダウンロード数、アカウントの情報をEthereumから取ってくるように命令
// 一旦、簡易的なデータを作ってアルゴリズムを実装する
struct Report {
string userAddress;
string reportHash;
uint16 downloads;
}
struct RP1Table {
string userAddress;
uint256 RP1;
}
Report[] public reports;
Report[] public reportsAbove;
Report[] public reportsBelow;
RP1Table[] public RP1Array;
constructor() public {
reports.push(Report("0xc9472850C2bbEBC689b581b92A2E1A694235c9e5", "R1", 600));
reports.push(Report("0xc9472850C2bbEBC689b581b92A2E1A694235c9e5", "R2", 700));
reports.push(Report("0xc9472850C2bbEBC689b581b92A2E1A694235c9e5", "R3", 800));
reports.push(Report("0x45c79bbE964d68beC3c8BeCAB9d3A7b7f7e9dDcd", "R4", 400));
reports.push(Report("0x45c79bbE964d68beC3c8BeCAB9d3A7b7f7e9dDcd", "R5", 500));
reports.push(Report("0x45c79bbE964d68beC3c8BeCAB9d3A7b7f7e9dDcd", "R6", 900));
reports.push(Report("0xA4682e519519f3D461DEEa60ed8f2A07d7ed7458", "R7", 100));
reports.push(Report("0xA4682e519519f3D461DEEa60ed8f2A07d7ed7458", "R8", 200));
reports.push(Report("0xA4682e519519f3D461DEEa60ed8f2A07d7ed7458", "R9", 300));
reports.push(Report("0x1FC6F20f2296628a7663902144Fc2D4507cCb5BD", "R10", 50));
}
// HPF():High Pass Filter
function HPF() public returns (RP1Table[] memory) {
uint16 _median = 0;
uint256 n = reports.length;
uint256 _numOfAbove = 0;
// 中央値を求める処理
Report[] memory sortReports = reports;
bubbleSort(sortReports); // ダウンロード数順にソート
if (n % 2 == 0) {
_median = (sortReportsn/2 - 1.downloads + sortReportsn/2.downloads) / 2; } else {
_median = sortReportsn/2.downloads; }
// 中央値以上/未満でレポートを分ける
for (uint i = 0; i < n; i++) {
if (sortReportsi.downloads >= _median) { reportsAbove.push(Report(sortReportsi.userAddress, sortReportsi.reportHash, sortReportsi.downloads)); } else {
reportsBelow.push(Report(sortReportsi.userAddress, sortReportsi.reportHash, sortReportsi.downloads)); }
}
// 評価の傾斜をかける処理
// 中央値以上のレポートには、レポートのダウンロード数が多い順にRPを与える
// RPはアドレスごとに集計する
_numOfAbove = reportsAbove.length;
if (_numOfAbove <= 8) {
for (uint i = 0; i < _numOfAbove; i++) {
RP1Array.push(RP1Table(reportsAbovei.reportHash, 40 - 5*i)); }
} else {
for (uint i = 0; i < _numOfAbove; i++) {
RP1Array.push(RP1Table(reportsAbovei.reportHash, 40 - 40*i/_numOfAbove)); }
}
// 中央値未満のレポートはRP=0
for (uint i = 0; i < reportsAbove.length; i++) {
RP1Array.push(RP1Table(reportsBelowi.userAddress, 0)); }
return RP1Array;
}
// swap関数
function swap(Report[] memory items, uint l, uint r) private pure {
Report memory t = itemsl; }
// バブルソート(降順)
function bubbleSort(Report[] memory items) public pure {
uint length = items.length;
for(uint i = 0; i < length-1; i++) {
for(uint j = i; j <length; j++) {
if(itemsj.downloads > itemsi.downloads) { swap(items, i, j);
}
}
}
}
}
https://gyazo.com/86474640ba1d3b4374cfedeac6560ffe・
mappingでもこんな感じで、テーブルを返したいです。
2. やったこと
mappingだと配列の大きさを返すライブラリが無いので、
こういうのを参考にして、ライブラリを自作して、それをインポートして使おうとしています。
とりあえず、データを格納できるかを確認したかったので、以下のような実装でデプロイしたら、このようなエラーが出てしまい行き詰まっています。
・エラー内容
https://gyazo.com/e4d36fe616bc2fa626eca8827f8cb2b5
・構造体にレポート情報を格納する方針で実装した時コード
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import 'contracts/IterableMapping.sol';
contract Algorithm {
struct Report {address userAddress;string reportHash;uint16 downloads;} // いらんかも
struct RP1Table {address userAddress;uint256 RP1;}
IterableMapping.Report[] public reports;
Report[] public reportsAbove;
Report[] public reportsBelow; // いらんかも
RP1Table [] public RP1Array;
IterableMapping.itmap reportsMapping;
mapping(uint8 => User) public userMapping;
constructor() public {
//RP1用のデータ
reports.push(IterableMapping.Report(0xc9472850C2bbEBC689b581b92A2E1A694235c9e5, "R1", 600));
reports.push(IterableMapping.Report(0xc9472850C2bbEBC689b581b92A2E1A694235c9e5, "R2", 700));
reports.push(IterableMapping.Report(0xc9472850C2bbEBC689b581b92A2E1A694235c9e5, "R3", 800));
reports.push(IterableMapping.Report(0x45c79bbE964d68beC3c8BeCAB9d3A7b7f7e9dDcd, "R4", 400));
reports.push(IterableMapping.Report(0x45c79bbE964d68beC3c8BeCAB9d3A7b7f7e9dDcd, "R5", 500));
reports.push(IterableMapping.Report(0x45c79bbE964d68beC3c8BeCAB9d3A7b7f7e9dDcd, "R6", 900));
reports.push(IterableMapping.Report(0xA4682e519519f3D461DEEa60ed8f2A07d7ed7458, "R7", 100));
reports.push(IterableMapping.Report(0xA4682e519519f3D461DEEa60ed8f2A07d7ed7458, "R8", 200));
reports.push(IterableMapping.Report(0xA4682e519519f3D461DEEa60ed8f2A07d7ed7458, "R9", 300));
reports.push(IterableMapping.Report(0x1FC6F20f2296628a7663902144Fc2D4507cCb5BD, "R10", 50));
IterableMapping.insert(reportsMapping, 0, reports0); IterableMapping.insert(reportsMapping, 1, reports1); IterableMapping.insert(reportsMapping, 2, reports2); IterableMapping.insert(reportsMapping, 3, reports3); IterableMapping.insert(reportsMapping, 4, reports4); IterableMapping.insert(reportsMapping, 5, reports5); IterableMapping.insert(reportsMapping, 6, reports6); IterableMapping.insert(reportsMapping, 7, reports7); IterableMapping.insert(reportsMapping, 8, reports8); IterableMapping.insert(reportsMapping, 9, reports9); }
// HPF():High Pass Filter (入力データが連想配列の場合)
function HPF() public returns (uint16) {
uint16 _median = 0;
uint8 n = reportsMapping.size;
// IterableMapping.itmap memory sortReports = reportsMapping;
uint256 _numOfAbove = 0;
// 中央値を求める処理
// bubbleSortMapping(sortReports); // ダウンロード数順にソート
if (n % 2 == 0) {
_median = (reportsMapping.datan/2 - 1.report.downloads + reportsMapping.datan/2.report.downloads) / 2; } else {
_median = reportsMapping.datan/2.report.downloads; }
// 中央値以上のレポートを取り出す
for (uint8 i = 0; i < n; i++) {
if (reportsMapping.datai.report.downloads >= _median) { reportsAbove.push(Report(reportsMapping.datai.report.userAddress, reportsMapping.datai.report.reportHash, reportsMapping.datai.report.downloads)); } else {
reportsBelow.push(Report(reportsMapping.datai.report.userAddress, reportsMapping.datai.report.reportHash, reportsMapping.datai.report.downloads)); }
}
// 評価の傾斜をかける処理
// 中央値以上のレポートには、レポートのダウンロード数が多い順にRPを与える
// RPはアドレスごとに集計する
_numOfAbove = reportsAbove.length;
if (_numOfAbove <= 8) {
for (uint i = 0; i < _numOfAbove; i++) {
RP1Array.push(RP1Table(reportsAbovei.userAddress, 40 - 5*i)); }
} else {
for (uint i = 0; i < _numOfAbove; i++) {
RP1Array.push(RP1Table(reportsAbovei.userAddress, 40 - 40*i/_numOfAbove)); }
}
// 中央値未満のレポートはRP=0
for (uint i = 0; i < reportsAbove.length; i++) {
RP1Array.push(RP1Table(reportsBelowi.userAddress, 0)); }
// return RP1Array;
return _median;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
// mappingのサイズなどを取得するためのライブラリ
library IterableMapping {
struct itmap { mapping(uint8 => IndexValue) data; KeyFlag[] keys; uint8 size; }
struct IndexValue { uint keyIndex; Report report; }
struct Report { address userAddress; string reportHash; uint16 downloads;}
struct KeyFlag { uint8 key; bool deleted; }
function insert(itmap storage self, uint8 key, Report memory report) public returns (bool replaced) {
uint keyIndex = self.datakey.keyIndex; self.datakey.report = report; if (keyIndex > 0)
return true;
else {
uint l = self.keys.length;
keyIndex = l++;
self.datakey.keyIndex = keyIndex + 1; self.size++;
return false;
}
}
function remove(itmap storage self, uint8 key) public returns (bool success) {
uint keyIndex = self.datakey.keyIndex; if (keyIndex == 0)
return false;
self.size --;
}
function contains(itmap storage self, uint8 key) public view returns (bool) {
return self.datakey.keyIndex > 0; }
function iterate_start(itmap storage self) public view returns (uint keyIndex) {
return iterate_next(self, uint(-1));
}
function iterate_valid(itmap storage self, uint keyIndex) public view returns (bool) {
return keyIndex < self.keys.length;
}
function iterate_next(itmap storage self, uint keyIndex) public view returns (uint r_keyIndex) {
keyIndex++;
while (keyIndex < self.keys.length && self.keyskeyIndex.deleted) keyIndex++;
return keyIndex;
}
function iterate_get(itmap storage self, uint keyIndex) public view returns (uint8 key, Report memory report) {
report = self.datakey.report; }
}
var IterableMapping = artifacts.require("IterableMapping");
var Algorithm = artifacts.require("Algorithm");
module.exports = function (deployer) {
deployer.deploy(IterableMapping);
deployer.link(IterableMapping, Algorithm);
deployer.deploy(Algorithm);
};
3. 質問
・今の段階でデプロイが失敗する原因が分かりません。
・Solidityで連想配列をソートしたりするのは実現可能か(できるんでしょうけど😅 )、また、実装の流れなどを教えて欲しいです。